<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/*user model by StevenY.*/
class User extends CI_Model {
	
	var $err_code=0;
	var $err_msg='';
	var $id;
	var $login=FALSE;
	var $email_key;
	
	//构造函数		
	function __construct()
	{
		parent::__construct();
		if ($this->session->userdata('login'))
		{
			// 已经成功登陆
			$this->id = $this->session->userdata('uid');
		}
		//$this->config->load('user',TRUE);
		//$this->email_key=$this->config['user']['email_key'];
		$this->email_key='asdfasfdasfdqwvqbbqerfwscasfwf';
	}
	
	function active()
	{
		$this->db->where('id',$this->id);
		$this->db->update('user',array('latest_active'=>date('Y-m-d H-i-s',time())));
	}

	//返回随机数列
	function get_key()
	{
		$this->load->helper('string');
		$key = random_string('alnum',32);
		
		//设置session记录验证随机数列
		$this->session->set_userdata('login_key', $key);
		
		//返回验证随机数列
		return $key;
	}
	
	//返回RSA mudulus	
	//从文件读取吧，如果不能做成从不允许直接访问目录读取，就从php脚本保护起来读取，还有可以把功能扩写进rsa类
	function get_rsa_mudulus()
	{
/*		$this->load->library('rsa');
		$this->rsa->load_privatekey();
		$this->rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
		return base64_encode($this->rsa->modulus->toBytes());
*/
		$this->load->library('rsa');
		return $this->rsa->get_modulus();
	}
	
	/*登陆验证,$uname为用户名,$str为客户端hash过的密码*/	
	function login($uname,$str)
	{
		//取出随机数列
		$login_key=$this->session->userdata('login_key');		
		$this->session->unset_userdata('login_key');

		/*获得用户信息*/
		if ($this->db->get_where('user',array('uname'=>$uname))->num_rows()>0)
		{
			$q=$this->db->get_where('user',array('uname'=>$uname))->row_array();
			//检查用户是否已经过期
			if (isset($q['expire_time']) && ($q['expire_time'] < time()))//验证待激活用户是否过期，过期则删除，并返回登陆失败
			{
				//删除信息
				$this->db->delete('user',array('id'=>$q['id']));
				$this->db->delete('user_info',array('uid'=>$q['id']));
				$this->err_code=101;
				$this->err_msg='用户已过期';
				return FALSE;
			}
		
			/*检验用户是否已经激活*/
			if (! $q['active'])
			{
				$this->err_code=102;
				$this->err_msg='用户未激活'.$q['active'].$q['uname'];
				return FALSE;
			}
			
			//检查用户是否已经被登陆
			if (($q['login_now']) && ($q['latest_active'] > time()-600))
			{
				$this->err_code=100;
				$this->err_msg='用户已经登录';
				return FALSE;
			}
			
			/*产生服务器端的hash数据*/
			$ser=sha1($q['pword'].$login_key);
			
			/*验证*/
			if ($str == $ser)
			{
				/*更新最后登陆时间以及登陆状态*/
				$this->db->where('id',$q['id']);
				$this->db->update('hfi_user',array(
												'latest_login'=>date('Y-m-d H-i-s',time()),
												'latest_active'=>time(),
												'login_now'=>TRUE
												));
				$this->err_code=0;
				
				//更新session
				$s_data=array(
						'login'=>TRUE,
						'uid'=>$q['id']
						);
				$this->session->set_userdata($s_data);
				
				//设置登陆数据
				$this->id=$q['id'];
				
				return TRUE; /*登陆成功*/
			}
			else
			{
			  $this->err_code=103;/*密码错误*/
			  $this->err_msg='密码错误';
			  return FALSE;
			}
		}
		else
		{
			$this->err_code=104;/*找不到用户名*/
			$this->err_msg='找不到用户名';
			return FALSE;
		}
	} 
	
	/*退出登陆,删除session*/	
	function logout()
	{
		//更改登陆状态
		if (isset($this->id))
		{
			$this->db->where('id',$this->id);
		}
		else
		{
			$this->db->where('id',$this->session->userdata('uid'));
		}
		$this->db->update('user',array('login_now'=>FALSE));

		
		//清除session
		if ($this->session->userdata('login'))
			$this->session->unset_userdata('login');
		
		$this->session->unset_userdata('uid');
		$this->session->unset_userdata('login_key');
		$this->session->unset_userdata('login_num');
		
		$this->err_msg ='SUCCESS';
		$this->err_code=0;
		return TRUE;

		$this->err_code=801;
		$this->err_msg='已经退出登录';
		return FALSE;

	}
	
	/*
	检查注册信息，成功则并发送验证邮件
	注册时,密码要先进行一次sha1,然后使用RSA
	$uname 为明文发送的用户名，$pword为RSA加密的密码,$emial为明文发送的安全邮箱,$cnln是中文拼音姓,$cnfn是中文拼音名字
	注册信息安全检查
	*/
	function regi_chk($uname,$pword,$cnfn,$cnln,$y,$email)
	{
		//用户自动审核:哪一届+中文名,表名:hfi_user_veri
		if (! ($this->db->get_where('user_veri', array( 'cnfn'=>strtoupper($cnfn),
														'cnln'=>strtoupper($cnln), 
														'year'=>$y))
														->num_rows() > 0))
		{
		  $this->err_code=201;
		  $this->err_msg='用户信息错误';
		  return FALSE;
		}
		
		//加载rsa类
		$this->load->library('rsa');
		$this->rsa->load_privatekey();
		$this->rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);

		
		/*验证用户名*/
		$v=$this->db->get_where('user',array('uname'=>$uname));
		if (($v->num_rows()>0))
		{
		  $this->err_code=202;/*用户名已存在*/
		  $this->err_msg='用户名已存在';
		  return FALSE;
		}
		
		/*验证邮箱*/
		if ($this->db->get_where('user',array('email'=>$email))->num_rows()>0)
		{
		  $this->err_code=203;
		  $this->err_msg='验证邮箱已被注册';
		  return FALSE;
		}
		$this->load->helper('email');
		$this->load->library('email');
		if (! valid_email($email))
		{
		  $this->err_code=204;/*邮箱地址无效*/
		  $this->err_msg='邮箱地址无效';
		  return FALSE;
		}
	  
		//密码解密
		$d_pword=$this->rsa->decrypt(base64_decode($pword));
	  
		/*将未激活账户存进数据库*/
		$this->db->trans_begin();
		
		//将未激活用户保存在user表
	  	$etime=time()+24*3600;//待激活用户24小时后过期
	  	$a=array(
			'uname'=>$uname,
			'pword'=>$d_pword,/*密码明文sha1后保存,前端hash过之后发送*/
			'email'=>$email,
			'active'=>FALSE,
			'create_time'=>date('Y-m-d H:i:s'),
			'expire_time'=>$etime 
			);
		$this->db->set($a);
		$this->db->insert('user');
		
		//将veri表的信息转移到user_info表
		$q=$this->db->get_where('user',array('uname'=>$uname))->row_array();
		$veri_info=$this->db->get_where('user_veri', array( 'cnfn'=>strtoupper($cnfn),
														'cnln'=>strtoupper($cnln), 
														'year'=>$y))->row_array();
		$this->db->set('cnfn',$veri_info['cnfn']);
		$this->db->set('cnln',$veri_info['cnln']);
		$this->db->set('year',$veri_info['year']);
		$this->db->set('uid',$q['id']);
		$this->db->insert('user_info');
		
		//数据库query检查完毕
		if($this->db->trans_status() === FALSE)
		{
			//错误则滚回
			$this->db->trans_rollback();
			$this->err_code=206;
			$this->err_msg='无法将数据载入数据库';
			return FALSE;
		}
		else  
		{
			$this->db->trans_commit();
			
			//产生加密URL
			$this->load->library('aes');
			$this->aes->setkey($this->email_key);
			$verti_url='u='.urlencode(base64_encode($this->aes->encrypt($uname)));
			
			/*发送验证邮件*/
			/*
			$this->email->initialize($config);
			$this->email->from('your@example.com', 'Your Name');
			$this->email->to($email); 
			$this->email->subject('Email Vertify');
			$this->email->message('验证接口'.$verti_url); //验证接口未定
			$this->email->send();
			*/
			
			$this->err_code=0;
			$this->err_msg='Success';
			return $verti_url;
			//return TRUE;
		}  
	}

	/*验证验证邮件并注册,$crypt为验证邮件返回的信息*/
	function regi_veri($crypt)
	{
		/*解密用户名*/  
		$this->load->library('aes');
		$this->aes->setkey($this->email_key);
		$uname=$this->aes->decrypt(base64_decode(urldecode($crypt)));
				
		/*获取数据库中记录*/
		$da=$this->db->get_where('user',array('uname'=>$uname))->row_array();
		
		//检查激活信息
		if ($da['active'])
		{
		  $this->err_code=301;
		  $this->err_msg='用户已激活';
		  return FALSE;
		}
		
		if ($this->db->get_where('user',array('uname'=>$uname))->num_rows()!=1)
		{
			$this->err_Code=310;
			$this->err_msg='what the hell!';
			return FALSE;
		}
		
		//验证待激活用户是否过期，过期则删除，并返回链接已过期
		if (! (isset($da['expire_time']) && ($da['expire_time']>time())))
		{
		  //删除信息
		  $this->db->delete('user_info',array('uid'=>$da['id']));
		  $this->db->delete('user',array('id'=>$da['id']));
		  $this->err_code=302;
		  $this->err_msg='链接已过期，请重新注册';
		  return FALSE;
		}

		//通过验证，将用户信息写入数据库
		$this->db->trans_begin();
		
		//修改用户激活信息
		$this->db->where('id',$da['id']);
		$this->db->update('user',array('active'=>TRUE,'expire_time'=>NULL));
		
		//确认用户隶属信息
		$a=array(
				'uid'=>$da['id'],
				'gid'=>4 //学生用户组的id，未定
				);
		$this->db->set($a);
		$this->db->insert('user_sub');
		
		//将veri表该信息删除，不可重复验证
		$d=$this->db->get_where('user_info',array('uid'=>$da['id']))->row_array();
		$this->db->delete('user_veri',array('cnln'=>$d['cnln'],'cnfn'=>$d['cnfn'],'year'=>$d['year']));
		
		//创建authid
		$this->db->set('table_name','user');
		$this->db->set('item_id',$da['id']);
		$this->db->insert('authid');
		
		//将authid存入user表
/*		$thid->db->select('authid');
		$authid=$this->db->get_where('authid',array('table_name'=>'user','item_id'=>$da['id']));
		$this->db->where('id',$da['id']);
		$this->db->update('user',array('authid'=>$authid));
*/
		
		if ($this->db->trans_status() === FALSE)
		{
			$this->db->trans_rollback();
			$this->err_code=304;//激活失败，请重试
			$this->err_msg='激活失败，信息无法写入数据库';
			return FALSE;
		}
		else
		{
			$this->db->trans_commit();
			$this->session->set_userdata('login',TRUE);
			$this->session->set_userdata('uid',$da['id']);
			$this->err_code=0;
			$this->err_msg='Success';
			return TRUE;//激活成功
		}
	}
	
	/*删除其它用户,$uid是被删除用户ID*/
	function deluser($uid)
	{		
		//验证权限
		
		//获取authid
		$this->db->select('authid');
		$authid=$this->db->get_where('user',array('uid'=>$uid));//取出$uid的authid
		
		//查询有没有用$uid的authid记录的权限信息
		if ($this->db->get_where('auth',array('authid'=>$authid,'uid'=>$this->id))->num_rows()>0)
		{
			//有就用该权限信息验权限
			if (! $this->get_auth($authid,'w')) return FALSE;
		}
		else//没有则查询以执行者所属用户组的authid
		{
			$this->db->select('gid');
			$gid=$this->db->get_where('user_sub',array('uid'=>$uid))->result_array();
			//多个用户组，则取其最高权限
			$auth= FLASE;
			foreach ($gid as $i=>$item)
			{
				if (! $this->get_auth($authid,'w')) return FALSE;
			}
		}
		
		/*删除数据库里面该用户的记录*/
		$this->db->trans_begin();
		
		$this->db->delete('user_sub',array('uid'=>$uid));
		$this->db->delete('user_info',array('uid'=>$uid));
		$this->db->delete('user',array('id'=>$uid));
		
		if ($this->db->trans_status() === FALSE)
		{
			$this->db->trans_rollback();
			$this->err_code=401;//删除用户失败
			$this->err_msg='删除用户失败';
			return FALSE;
		}
		else
		{
			$this->db->trans_commit();
			$this->err_code=0;
			$this->err_msg='Success';
			return TRUE;
		}
	}
	
	/*用户自己修改密码*/
	/*$crypt:原密码用sha1+随机数列再sha1发送 $npword用sha1+随机数列+RSA加密*/
	function chpword($crypt,$npword)
	{
		//获取
		$check_key=$this->session->userdata('key');
		$this->session->unset_userdata('key');
		
		//验证旧密码
		$q=$this->db->get_where('user',array('uname'=>$this->id))->row_array();
		if (isset($q['id']))
		{
			//检查用户是否已经过期
			if (isset($q['expire_time']) && ($q['expire_time']>time()))//验证待激活用户是否过期，过期则删除，并返回登陆失败
			{
				//删除信息
				$this->db->delete('user',array('id',$q['id']));
				$this->err_code=501;
				$this->err_msg='用户已过期,请重新注册';
				
				//处理session
				$this->session->set_userdata('login',FALSE);
				$this->session->unset_userdata('uid');
				return FALSE;
			}
			/*产生服务器端的hash数据*/
			$ser=sha1($q['pword'].$check_key);
			
			/*验证*/
			if (! $str == $ser)
			{
				$this->err_code=502;/*密码错误*/
				$this->err_msg='密码错误';
				return FALSE;
			}
		}
		else
		{
			$this->err_code=503;/*找不到用户名*/
			$this->err_msg='找不到用户名';//处理session
			$this->session->set_userdata('login',FALSE);
			$this->session->unset_userdata('uid');		
			return FALSE;
		}
		
		//新密码解密
		$this->load->library('rsa');
		$this->rsa->load_privatekey();//载入私钥
		$this->rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
		$d_pword=$this->rsa->decrypt(base64_decode($npword));
		 
		/*保存新密码*/
		$this->db->where('id',$id);
		if($this->db->update('user',array('pword'=>$d_pword)))
		{
			$this->err_code=0;
			$this->err_msg='Success';
			return TRUE; 
		}
		else
		{
			$this->err_code=504;
			$this->err_msg='数据库错误';
			return FALSE; 
		}
	}
/*		
	//添加用户到，$uid为
	function add_user($uid,$b)
	{
		$ck_id=$this->session->userdata('uid');
		//验证权限,只有0和1这两个组可以进行该操作
		if (($this->db->get_where('user_sub',array('gid'=>0,'uid'=>$ck_id))->row_nums()>0) ||
			($this->db->get_where('user_sub',array('gid'=>1,'uid'=>$ck_id))->row_nums()>0))
		{
			
		}
		else
		{
			
		}
	}
*/
	
	//更改其他用户资料, $a包含新用户信息的数组,只能修改非安全类信息
	//$uid是被修改的用户id
	function chinfo($uid,$a)
	{
		//验证权限
		
		//获取authid
		$this->db->select('authid');
		$authid=$this->db->get_where('user',array('uid'=>$uid));//取出$uid的authid
		
		//查询有没有用$uid的authid记录的权限信息
		if ($this->db->get_where('auth',array('authid'=>$authid,'uid'=>$this->id))->num_rows()>0)
		{
			//有就用该权限信息验权限
			if (! $this->get_auth($authid,'w')) return FALSE;
		}
		else//没有则查询以执行者所属用户组的authid
		{
			$this->db->select('gid');
			$gid=$this->db->get_where('user_sub',array('uid'=>$uid))->result_array();
			//多个用户组，则取其最高权限
			$auth= FLASE;
			foreach ($gid as $i=>$item)
			{
				if (! $this->get_auth($authid,'w')) return FALSE;//$authid??
			}
		}
				
		//检查信息,检查appendix
		if (isset($a['appendix']))
		{
			$this->load->library('secuirty');
			$a['appendix']=$this->security->xss_clean($a['appendix']);
		}
		
		$this->db->set($a);
		if ($this->db->update('user_info',array('uid'=>$uid)))
		{
			$this->err_code=0;
			$this->err_msg='Success';
			return TRUE;
		}
		else
		{
			$this->err_code=601;//更改用户资料失败
			$this->err_msg='更改用户资料失败';
			return FALSE;
		}
	}
	
	/*获取用户信息*/
	function get_info()
	{
/*		//验证权限
		
		//获取authid
		$this->db->select('authid');
		$authid=$this->db->get_where('user',array('uid'=>$uid));//取出$uid的authid
		
		//查询有没有用$uid的authid记录的权限信息
		if ($this->db->get_where('auth',array('authid'=>$authid,'uid'=>$this->id))->num_rows()>0)
		{
			//有就用该权限信息验权限
			if (! $this->get_auth($authid,'w')) return FALSE;
		}
		else//没有则查询以执行者所属用户组的authid
		{
			$this->db->select('gid');
			$gid=$this->db->get_where('user_sub',array('uid'=>$uid))->result_array();
			//多个用户组，则取其最高权限
			$auth= FLASE;
			foreach ($gid as $i=>$item)
			{
				if (! $this->get_auth($authid,'w')) return FALSE;//$authid??
			}
		}
		

		/*获取信息*/
		$uid=$this->id;

		$this->db->trans_begin();
		$p['user']=$this->db->get_where('user',array('id'=>$uid))->row_array();
		$p['sub']=$this->db->get_where('user_sub',array('uid'=>$uid))->row_array();
		$p['user_info']=$this->db->get_where('user_info',array('uid'=>$uid))->row_array();
		
		if ($this->db->trans_status() === FALSE)
		{
			$this->db->trans_rollback();
			$this->err_code=701;//获取用户信息失败
			$this->err_msg='获取用户信息失败';
			return FALSE;
		}
		else
		{
			$this->db->trans_commit();
			$this->err_code=0;
			$this->err_msg='Success';
			return $p;
		}
	} 
	
	/*找回密码,发送验证邮件*/
	//$uname为用户名,$email为用户填写的安全邮箱用sha1加密之后的字符
	//找回密码的连接有漏洞
	function re_send($uname,$email)
	{
		$d=$this->db->get_where('user',array('uname'=>$uname));
		if ($d->num_rows()>0)	
		{
			$da=$d->row_array();
			if (sha1($da['email'])==$email)
			{
				//用AES加密
				$this->load->library('aes');
				$this->aes->setKey($this->email_key);//密匙为发起请求的IP地址和随机数列
				$random=random_string('alnum',16);//邮箱验证随机数
				$url='u='.urlencode(base64_encode($this->aes->encrypt($uname))).
								'&d='.urlencode(base64_encode($this->aes->encrypt(time()))).
								'&r='.urlencode($random);//用当前时间和用户名来加密
				//将$random储存如appendix
				$q=$this->db->get_where('user_info',array('uid'=>$da['id']))->row_array();
				$appendix_a=unserialize($q['appendix']);
				$appendix_a['reset_key']=$random;
				$appendix_s=serialize($appendix_a);
				$this->db->update('user_info',array('appendix'=>$appendix_s),array('uid'=>$da['id']));
				
				/*发送验证邮件*/
				/*
				$this->load->library('email');
				$this->email->from('your@example.com', 'Your Name');
				$this->email->to($d->email); 
				$this->email->subject('Email Vertify');
				$this->email->message('验证接口'.$url); //验证接口未定
				$this->email->send();
				*/
				
				$this->err_code=0;
				$this->err_msg='Success';
				return site_url('entrance/email_recieve').'?'.$url;
				return TRUE;
			}
			else
			{
				$this->err_code=1101;
				$this->err_msg='用户邮箱错误';
				return FALSE;
			}
		}
		else
		{
			$this->err_code=1102;
			$this->err_msg='用户名不存在';
			return FALSE;
		}
	}
	
	//验证找回密码链接
	function re_verti($u,$d,$r)
	{
		//AES解密
		$this->load->library('aes');
		$this->aes->setKey($this->email_key);
		$uname=$this->aes->decrypt(base64_decode(urldecode($u)));
		$time=$this->aes->decrypt(base64_decode(urldecode($d)));
		
		//验证链接是否过期,有效期为一天
		if ($time<(time()-24*3600))
		{
			$this->err_code=1201;
			$this->err_msg='链接已过期'.$time;
			return FALSE;
		}
		
		//验证用户名
		if ($this->db->get_where('user',array('uname'=>$uname))->num_rows()!=1)
		{
			$this->err_code=1202;
			$this->err_msg='链接错误';
			return FALSE;
		}
		
		//验证随机数是否有效(即链接是否有效)
		$d=$this->db->get_where('user',array('uname'=>$uname))->row_array();
		$q=$this->db->get_where('user_info',array('uid'=>$d['id']))->row_array();
		$appendix_a=unserialize($q['appendix']);
		if ($appendix_a['reset_key']!=$r)
		{
			$this->err_code=1203;
			$this->err_msg='链接无效'.$appendix_a['reset_key'];
			return FALSE;
		}
		
		//处理session
		$this->session->set_userdata('pwreset',TRUE);
		$this->session->set_userdata('uid',$d['id']);
		//处理数据库
		$appendix_a['reset_key']='';
		$appendix_s=serialize($appendix_a);
		$this->db->update('user_info',array('appendix'=>$appendix_s),array('uid'=>$d['id']));
		
		//返回成功
		$this->err_code=0;
		$this->err_msg='Success';
		return TRUE;
	}
	
	//找回密码的新密码,$npword为sha1过的新密码再用RSA加密
	function re_setnp($npword)
	{	
		if ($this->session->userdata('pwreset'))
		{
			//新密码解密
			$this->load->library('rsa');
			$this->rsa->load_privatekey();//载入私钥
			$this->rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
			$d_pword=$this->rsa->decrypt(base64_decode($npword));
			 
			/*保存新密码*/
			if (! $this->db->update('user',array('pword'=>$d_pword),array('id'=>$this->session->userdata('uid'))))
			{
				$this->err_code=1301;
				$this->err_msg='修改密码失败';
				return FALSE;
			}
			
			$this->err_code=0;
			$this->err_msg='Success'.$d_pword;
			$this->session->unset_userdata('pwreset');
			$this->session->set_userdata('login',TRUE);

			return TRUE; 
		}
		else
		{
			$this->err_code=1302;
			$this->err_msg="DON'T MESS UP ON ME T.T";
			$this->session->unset_userdata('pwreset');
			$this->session->unset_userdata('uid');
			return FALSE;
		}
	}
	
	/*对于当前用户添加，删除，修改，获取信息操作验证权限的函数*/
	/*$uid是执行对象的id,$a是权限标识:'r','w','c','d'*/
	function get_auth($authid,$method)
	{
		//检查权限标识
		if (! (($method=='r') || ($method=='d') || ($method=='w') ||($method=='c')))
		{
			$this->err_code=1001;
			$this->err_msg='权限参数错误';
			return FALSE;
		}
		
		//用执行对象和authid直接查询
		if ($this->db->get_where('auth',array('uid'=>$this->id,'authid'=>$authid))->num_rows()>0)
		{
			$data=$this->db->get_where('auth',array('uid'=>$this->id,'authid'=>$authid))->row_array();
			$this->err_code=0;
			$this->err_msg='SUCCESS';
			return $data[$method];
		}
		else //如果auth表里面没有用uid记录的特殊权限,则用uid所属的用户组的gid
		{
			$sub=$this->db->get_where('user_sub',array('uid'=>$this->id))->result_array();
			//多重则隶属,取最高权限
			$auth=FALSE;
			foreach ($sub as $i=>$tiem)//判断uid的每一个隶属组有没有对authid相关method的权限
			{
				$q=$this->db->get_where('auth',array('authid'=>$authid,'uid'=>$tiem['gid']))->row_array();
				if ($q[$method])//只要其中一个隶属组有该权限则uid有相关权限
				{
					$this->err_code=0;
					$this->err_msg='SUCCESS';
					return TRUE;
				}
			}
			$this->err_code=1000;
			$this->err_msg='NO PERMISSION';
			return $auth;	
		}
	}
	
	/*返回错误码*/
	function get_err_code()
	{
	  return $this->err_code;
	}
	
	/*返回错误信息*/
	function get_err_msg()
	{
	  return $this->err_msg;
	}

}
/*End of file user.php*/